'use strict';

const Service = require('egg').Service;
const { errors } = require('../errors');
const _ = require('lodash');

class BaseService extends Service {
  constructor(ctx) {
    super(ctx);
    this.include = [];
    this.exclude = [];
    this.projection = ctx.helper.buildProjection(this.include, this.exclude);
    this.errors = errors;
  }

  async create(payload) {
    this.preCreate && this.preCreate(payload);
    return this._Model.create(payload);
  }

  async update(_id, payload) {
    const { _Model } = this;
    const movie = await _Model.findOne({ _id });
    if (!movie) {
      throw errors.NotFoundError('NotFound' + this._Model.modelName, this._Model.modelName + ' is not found');
    }

    return _Model.findByIdAndUpdate(_id, payload);
  }

  async show(_id) {
    const model = await this._Model.findOne({ _id })
      .populate(this.populate)
      .lean();

    if (!model) {
      throw errors.NotFoundError('NotFound' + this._Model.modelName, this._Model.modelName + ' is not found');
    }
    return model;
  }

  async destroy(_id) {
    const model = await this._Model.findOne({ _id });
    if (!model) {
      throw errors.NotFoundError('NotFound' + this._Model.modelName, this._Model.modelName + ' is not found');
    }

    await this._Model.removeOne({ _id });
    return model;
  }

  async index(payload) {
    const { ctx, populate, projection, _Model } = this;
    payload = ctx.helper.convertRestQueryParams(payload);
    let res = [];
    res = await ctx.helper.buildQuery({
      model: _Model,
      filters: payload,
      populate,
      projection,
    });
    return res;
  }

}

module.exports = BaseService;
